#include "lvgl/lvgl.h"              // LVGL 核心头文件
#include "lvgl/demos/lv_demos.h"    // LVGL 官方 demo 集合
#include "lv_drivers/display/fbdev.h" // Linux FrameBuffer 驱动
#include "lv_drivers/indev/evdev.h"   // Linux 输入事件（鼠标/触摸）驱动
#include "usrCode/myFunc.h"
#include <unistd.h>                 // usleep
#include <pthread.h>                // 线程相关（本例未实际用到）
#include <time.h>                   // gettimeofday
#include <sys/time.h>               // 同上

#define DISP_BUF_SIZE (1024 * 1024)  // 显存缓冲区总字节数（1024 kB）

/* 前置声明，避免“隐式声明”警告 */
void lv_example_btn_1(void);

int main(void)
{
    /* 1. 初始化 LVGL 内核 */
    lv_init();

    /* 2. 初始化 FrameBuffer 显示设备 */
    fbdev_init();

    /* 3. 静态分配一块显存缓冲区 */
    static lv_color_t buf[DISP_BUF_SIZE];  // 字节数组，真正像素数据放这里

    /* 4. 把原始字节数组包装成 LVGL 可识别的“显示描述符” */
    static lv_disp_draw_buf_t disp_buf;
    lv_disp_draw_buf_init(&disp_buf, buf, NULL, DISP_BUF_SIZE);  // 第三个参数为 NULL 表示单缓冲

    /* 5. 组装显示驱动结构体 */
    static lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);        // 先清零/赋默认值
    disp_drv.draw_buf   = &disp_buf;    // 关联缓冲区
    disp_drv.flush_cb   = fbdev_flush;  // 注册“把像素刷到屏幕”的回调
    disp_drv.hor_res    = 800;          // 屏幕宽
    disp_drv.ver_res    = 480;          // 屏幕高
    lv_disp_drv_register(&disp_drv);    // 向 LVGL 注册这套驱动

    /* 6. 初始化 evdev 输入子系统（鼠标/触摸） */
    evdev_init();

    /* 7. 组装输入设备驱动结构体 */
    static lv_indev_drv_t indev_drv_1;
    lv_indev_drv_init(&indev_drv_1);    // 清零/默认值
    indev_drv_1.type = LV_INDEV_TYPE_POINTER;  // 指针类设备（鼠标/触摸）
    indev_drv_1.read_cb = evdev_read;   // 注册“读取坐标/状态”的回调
    lv_indev_t *mouse_indev = lv_indev_drv_register(&indev_drv_1);  // 注册
    (void)mouse_indev;  // 消除“未使用变量”编译警告

    /* 8. 运行官方 demo（widgets 合集） */
    // lv_demo_widgets();  // 生成各种控件界面；无阻塞，立即返回

    myMain();
    /* 9. 主循环：负责 LVGL 心跳与刷新 */
    while(1) {
        lv_timer_handler();  // 处理所有 LVGL 内部定时器、动画、输入等事务
        lv_tick_inc(5);      // 告诉 LVGL“又过了 5 毫秒”
        usleep(5000);        // 真正延时 5 ms（1000 μs = 1 ms）
    }

    return 0;
}

/* 用户自定义的毫秒节拍获取函数（本例未实际被调用，但留着备用） */
uint32_t custom_tick_get(void)
{
    static uint64_t start_ms = 0;
    if(start_ms == 0) {
        struct timeval tv_start;
        gettimeofday(&tv_start, NULL);
        start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
    }

    struct timeval tv_now;
    gettimeofday(&tv_now, NULL);
    uint64_t now_ms;
    now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;

    uint32_t time_ms = now_ms - start_ms;
    return time_ms;
}